package beanstao.util.reflect;

import java.lang.reflect.Method;

/**
 * 利用java反射调用类的的私有方法
 * 
 * @author beanstao@google.com 
 */
@SuppressWarnings("unchecked")
public class InvokePrivateMethod
{
	/**
	 * 利用递归找一个类的指定方法，如果找不到，去父亲里面找直到最上层Object对象为止。
	 * 
	 * @param clazz 目标类
	 * @param methodName 方法名
	 * @param classes 方法参数类型数组
	 * @return 方法对象
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static Method getPrivateMethod(Class clazz, String methodName, Class... classes)
	{
		Method method = null;
		try
		{
			method = clazz.getDeclaredMethod(methodName, classes);
		}
		catch (Exception e1)
		{
			try
			{
				method = clazz.getMethod(methodName, classes);
			}
			catch (Exception e2)
			{
				if (clazz.getSuperclass() == null)
					return method;
				else
					method = getPrivateMethod(clazz.getSuperclass(), methodName, classes);
			}
		}
		return method;
	}

	/**
	 * @param obj 调整方法的对象
	 * @param methodName 方法名
	 * @param classes 参数类型数组
	 * @param objects 参数数组
	 * @return 方法的返回值
	 */
	@SuppressWarnings("rawtypes")
	public static Object invoke(final Object obj, final String methodName, final Class[] classes, final Object[] objects)
	{
		try
		{
			Method method = getPrivateMethod(obj.getClass(), methodName, classes);
			method.setAccessible(true);// 调用 private方法的关键一句话
			return method.invoke(obj, objects);
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}

	public static Object invoke(final Object obj, final String methodName, @SuppressWarnings("rawtypes") final Class[] classes)
	{
		return invoke(obj, methodName, classes, new Object[] {});
	}

}
